﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using Tsanie.ShellExtension;
using System.IO;

namespace Tsanie {

    [ComVisible(true)]
    [Guid("C13769FE-8B1A-40F3-92DD-4367A277623A")]
    [ExtensionFileTypes("Folder", FindAssoc = false)]
    public class Md5PropertyHandler : ColumnProviderBase {

        public override void Initialize(ShellColumnInitializeInfo shellColumnInitializeInfo) {
            Common.OutputDebugString("Initialize():: Folder = " + shellColumnInitializeInfo.Folder);
        }

        public override int GetColumnInfo(int index, out ShellColumnInfo columnInfo) {
            columnInfo = new ShellColumnInfo();
            if (index != 0) {
                Common.OutputDebugString("GetColumnInfo():: index = " + index);
                return 1;
            }
            try {
                columnInfo.ColumnId.FormatId = this.GetType().GUID;
                columnInfo.ColumnId.PropertyId = 0;

                columnInfo.variantType = (ushort)VarEnum.VT_BSTR;
                columnInfo.Format = ListViewAlignment.Left;
                columnInfo.DefaultWidthInCharacters = 40;
                columnInfo.State = ShellColumnState.TypeString;

                columnInfo.Title = "MD5 Hash";
                columnInfo.Description = "Provides an MD5 Hash of every file";

            } catch (Exception e) {
                Common.OutputDebugString("GetColumnInfo():: Exception, {0} - {1}", e.GetType().FullName, e.Message);
                return 1;
            }
            return 0;
        }

        public override int GetItemData(ref ShellColumnId columnId, ref ShellColumnData columnData, out object pvarData) {
            pvarData = string.Empty;

            // Ignore directories
            if ((columnData.FileAttributes & FileAttributes.Directory) == FileAttributes.Directory)
                return 1;

            // Only service my columns
            if (columnId.FormatId != this.GetType().GUID || columnId.PropertyId != 0)
                return 1;

            try {
                System.Security.Cryptography.MD5 md5 = new System.Security.Cryptography.MD5CryptoServiceProvider();
                byte[] result;
                using (Stream stream = File.OpenRead(columnData.File)) {
                    result = md5.ComputeHash(stream);
                    stream.Close();
                }
                StringBuilder output = new StringBuilder(2 + (result.Length * 2));
                for (int i = 0; i < result.Length; i++) {
                    output.Append(result[i].ToString("x2"));
                }
                pvarData = output.ToString();
            } catch (Exception e) {
                Common.OutputDebugString("GetItemData()::  File = {0}, {1} - {2}", columnData.File, e.GetType().FullName, e.Message);
                return 1;
            }

            return 0;
        }
    }
}
